<html>
<head><title>Swirrel</title>
</head>
<body>
<h1>Swirrel</h1>
Daniel Gronau, 2009-08-16

<h2>Introduction</h2>
<p>Swirrel is a little framework which allows to annotate AWT or Swing Components instead of writing listeners. Swirrel reads the annotations
and attaches the aproriate listeners automatically. All you have to do is to provide the name of the methods which should be called by the 
Swirrel listener. Swirrel is a double edged sword, it can make things much easier, but you can shoot yourself in the foot 
(hey, a sword you can shoot with!). Please consider carefully if Swirrel is right for you and your project. Don't use Swirrel for deeply 
nested, complex and/or time critical GUIs. Note that using Swirrel requires more testing, as things that caused compile time errors before
cause runtime errors now.</p>
<p>The name "Swirrel" is a combination of "Swing" and "squirrel" (the latter inspired by the way you have to climb through the class
hierarchy to get that job done).</p>

<h2>The Rules</h2>
<p>Swirrel relies on reflection which means things can go wrong if you don't follow these recommendations:<br/>
<ul>
<li>Of course the annotated field must support the listener type, e.g. annotating a JLabel with a call to ActionListener.actionPerformed results
in an exception.
<li>The name of the annotation is @org.swirrel.annotation.&lt;MethodName>, where &lt;MethodName> is the name of the method in the listener.
E.g. if you want to delegate a ActionListener.actionPerformed() call, the name of the Annotation is @ActionPerformed.</li>
<li>The annotation has one default String argument, containg the name of the method to call (the "handler method"). It must not contain
class names, dots, brackets, spaces etc. E.g. if you want a button click delegated to a method "doSomething", you would annotate with 
@ActionPerformed("doSomething"). The PropertyChangeListener syntax is different, see below.</li>
<li>One field may only have one annotation of each annotation type, e.g. you can't use @ActionPerformed twice for the same button.</li>
<li>One handler method can be called by several listeners</li>
<li>The handler method should have either no argumens or an argument matching the event object (e.g. ActionEvent for ActionListeners).
You can also use a super class of the event object (like java.lang.Object), e.g. to use one handler method to handle different listener
types.</li>
<li>The handler method must be defined in the class containg the annotated field, or in one of its base classes, or in one of the 
recursive parent classes (the Container classes returned by getParent(), or in one of their base classes etc). 
The search takes place in exactly that order, using the first matching method. E.g. you could have all your handler methods in the main Frame,
even if your annotated fields reside in some subpanels</li>
<li>Both annotated components and handler methods can be private, as long as the security policy allows Swirrel to call 
setAccisible(true).</li>
<li>Swirrel does nothing about runtime exceptions. If Swirrel detects an error itself, it throws a SwirrelException.
All checked exceptions are wrapped in SwirrelExceptions as well. I know this may be considered bad style, but my reasonig was that
at some point you get your GUI right and it just runs - there is no reason to deal with imaginary IllegalAccessExceptions etc in your code 
till the dawn of time.</li>
<li>I strongly suggest to add an comment like "handler of xyButton" to every handler method in order to avoid problems when renaming or 
deleting these methods. Some IDEs mark private handler methods as "unused", and someone might be tempted to "clean up" your code.</li>
</ul></p>

<h2>PropertyChangeListener</h2>
<p>PropertyChangeListeners are special, as they may include the name of the property. The syntax for a single annotation is:<br/>
<code>@PropertyChangeCall(method="handlePropertyChange" property="size")</code><br/>
The property argument is optional, but even if you leave it off, you have to write method=...<br>
As mentioned in the rules, you can have only one annotation of an annotation type for a given member, so if you have more than one 
PropertyChange event to handle, you need to "wrap" the annotations in an enclosing @PropertyChange<b>s</b> annotation:<br/>
<code><pre>
@PropertyChanges({
  @PropertyChange(method="handleSize" property="size"),
  @PropertyChange(method="handleLoc" property="location")
  @PropertyChange(method="handleEveryting")
})
</pre></code></br/>
Note that you still need to have different properties, else an exception is thrown.</p> 

<h2>Pros</h2>
<p><ul>
<li>Shorter code, no clutter due to anonymous classes</li>
<li>Very easy to use (in fact easier than usual listeners)</li>
<li>Great for prototyping</li>
<li>Convenient subclasses of JFrame etc, which initialize themselve when opening</li>
<li>You need to know the name of the listener method only, and not the name of the listener itself (or the name of the event object). 
E.g. if you want to track when the mouse is dragged, you annotate the member simply with @MouseDraggedCall, no need to remember that 
it is part of MouseMotionListener.</li>
<li>No all-or-nothing decision, you can still use old-style listeners</li>
</ul></p>

<h2>Cons</h2>
<p><ul>
<li>Uses reflection, which may result in a performence hit in complex GUIs</li>
<li>All annotated components must be member variables</li>
<li>If you change your GUI dynamically you have to call Swirrel.process() or SwFrame.process() etc. again</li>
<li>Errors show up at runtime instead of compile time (but usually immediately after opening the window)</li>
<li>If you use "normal" components like JFrame (instead of SwFrame) you may forget to call Swirrel.process()</li>
<li>The method which will be called is given by its name only. If you have several methods of the same name, the wrong
one could be called, especially when moving, renaming or deleting methods.</li>
<li>Changes in the security policy may invalidate Swirrel based code, as is tries to access private fields and methods.</li>
<li>org.swirrel.Swirrel is a Utility class like java.lang.Math: everything is static. Some people think this is code smell and
makes testing harder.</li>
</ul></p> 

<h2>Supported Listeners</h2>
<p>Currently the following listeners are supported:<br/>
<p><ul>
<li>ActionListener (actionPerformed)</li>
<li>FocusListener (focusGained, focusLost)</li>
<li>ItemListener (itemStateChange)</li>
<li>KeyListener (keyTyped, keyPressed, keyReleased)</li>
<li>ListSelectionListener (valueChanged)</li>
<li>MouseListener (mouseClicked, mousePressed, mouseReleased, mouseEntered, mouseExited)</li>
<li>MouseMotionListener (mouseMoved, mouseDragged)</li>
<li>MouseWheelListener (mouseWheelMoved)</li>
<li>PropertyChangeListener (propertyChange)</li>
</ul><br/>
The Swirrel library is considered "closed", there is no way to "register" support for other listeners. So you have to change the 
library sources to do this, but that's easy as there is already a lot of supporting infrastructure. Assume you want to add support for 
FooListener. Follow these steps:</p>
<p><ul>
<li>For each method in FooListener, add an annotation in org.swirrel.annotation</li>
<li>Write a SwirrelFooListener in org.swirrel.listener</li>
<li>Write a FooListenerInstaller in org.swirrel.installer</li>
<li>Add the FooListenerInstaller to the installers List in org.swirrel.Swirrel</li>
<li>Send me the patch :-)</li>
</ul><br/></p>

<h2>The Future</h2>
<p>The obvious thing to try would be using byte code enhancement instead of reflection. This would solve many of the problems of the
reflection magic and would give a speed advantage. I have no experience with this, so any help would be much appreciated.</p>
</body>
</html>